﻿using log4net;
using RemoteData.core.queue;
using RemoteData.model;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows;


namespace RemoteData.core.Listener
{
    public class DeviceDataWorker
    {
        private static ILog logger = LogManager.GetLogger(typeof(DeviceDataWorker));

        private readonly object locker = new object();

        public OPM_MsgDispatcher msgDispatcher = new OPM_MsgDispatcher();

        private ListeningState status;
        private Thread thWorker = null;
        private bool stopFlag = true;

        public int port { get; set; }

        private UdpClient udpClient;
        private IPEndPoint remoteEndPoint;
       

        public DeviceDataWorker()
        {
            status = ListeningState.UNLISTENING;
        }

        public DeviceDataWorker(int port): this()
        {
            this.port = port;
        }

        public int Listening()
        {
            int rn = 0;
            try
            {
                if (udpClient != null)
                {
                    udpClient.Close();
                }
                udpClient = new UdpClient(port);
                remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
                status = ListeningState.LISTENING;
            }
            catch(Exception ex)
            {
                status = ListeningState.UNLISTENING;
                logger.Error("启动监听失败");
                rn = -1;
            }
            return rn;
        }

        public void DisListening()
        {
            stopFlag = true;
            udpClient.Close();
        }

        public ListeningState GetStatus()
        {
            lock(locker)
            {
                return status;
            }
        }

        public int StartReceiveSync()
        {
            int rn = 0;
            if (stopFlag)
            {
                thWorker = new Thread(new ThreadStart(()=> StartReceive()));
                if(thWorker != null)
                {
                    thWorker.Start();
                }
                else
                {
                    rn = -1;
                }
            }
            return rn;
        }

        private int index = 0;
        private int channelNum = 0;
        private byte[] spectrumData = new byte[3096];
        public void StartReceive()
        {
            stopFlag= false;
            int msgLen = 0;
            int rn = 0;

            while(!stopFlag)
            {
                try
                {
                    if(status == ListeningState.UNLISTENING)
                    {
                        rn = Listening();
                        if(rn != 0)
                        {
                            Thread.Sleep(500);
                            continue;
                        }
                    }
                    else
                    {
                        if(udpClient.Available > 0 || udpClient.Client.Poll(3000,SelectMode.SelectRead))
                        {
                            byte[] receiveBytes = udpClient.Receive(ref remoteEndPoint);
                            msgLen = receiveBytes.Length;
                            if ((msgLen != 266))
                            {
                                continue;
                            }

                            //if (receiveBytes[262] != 0x00 && receiveBytes[263] != 0x00)
                            //{
                                byte c = receiveBytes[264];
                                int channel = (c >> 4)&0x0F;
                                int s = c & 0x03;
                                int ss = s * 256 + receiveBytes[265];
                                //Console.WriteLine(channel + ":" + ss + ":"+index);
                            if (ss == 0)
                            {
                                index = 0;
                            }
                                if(index == ss)
                                {
                                    channelNum = channel;
                                    Array.Copy(receiveBytes, 258, spectrumData, index * 6, 6);
                                    index++;
                                    if (index> 374)
                                    {
                                        SpectrumData spData = new SpectrumData();
                                        OPM_Protocol.ParseSpectrumPackage(spectrumData,msgLen, ref spData);
                                        spData.type = QueueDataType.DATA_SP;
                                        msgDispatcher.NotifyAll(spData);
                                        index = 0;
                                    }
                                }
                                else
                                {
                                    index = 0;
                                    channelNum = 0;
                                }
                            //}

                            QueueData data = null;
                            Wave waveLen = new Wave();
                            OPM_Protocol.ParseWaveLenPackage(receiveBytes,msgLen, ref waveLen);
                            waveLen.type = QueueDataType.DATA_WL;
                            data = waveLen;

                            msgDispatcher.NotifyAll(data);
                        }
                    }
                }
                catch (Exception ex)
                {
                    logger.ErrorFormat("数据接收报错:{0}", ex.Message);
                }
            }
        }

        public void StopReceive()
        {
            stopFlag = true;
        }

        public bool IsStop()
        {
            return stopFlag;
        }

        public void Join()
        {
            try
            {
                if (thWorker != null)
                {
                    thWorker.Join();
                }
            }
            catch(Exception)
            {
                string errMsg = string.Format("worker {0} Join操作异常", thWorker.ManagedThreadId);
                logger.ErrorFormat(errMsg);
            }
        }

        /// <summary>
        /// 等待线程结束
        /// (超时退出)
        /// </summary>
        public bool Join(int milliSeconds)
        {
            bool flag = true;
            if (thWorker != null)
            {
                try
                {
                    flag = thWorker.Join(milliSeconds);
                }
                catch (Exception)
                {
                    string errMsg = string.Format("device data receiver {0} Join操作异常", thWorker.ManagedThreadId);
                    logger.ErrorFormat(errMsg);
                }
            }

            return flag;
        }
    }
}
